package preorder
import (
    "time"
	"strings"
	"errors"
	"dhfshop/models"
	//"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"dhfshop/models/consts"
)

//预约周期管理
type Periods struct {
	PeriodsId    int64       `orm:"column(periods_id);pk;auto" json:"periods_id" form:"periods_id"`
	PartnerId    int64        `orm:"column(partner_id)" json:"partner_id" form:"partner_id"`  //商户ID
    ResItem      *ResItem     `orm:"column(res_item_id);rel(fk);on_delete(cascade)" json:"-" form:"-"` //级联删除
    ResItemId    int64        `orm:"-" json:"res_item_id" form:"res_item_id"`
	Name         string       `orm:"column(name);size(128);null" json:"name" form:"name"`       //名称,比如:周一、周二...
	SourceAt     time.Time    `orm:"column(source_at);type(date)" json:"-" form:"-"`            //号源时间,只要日期到天
    SourceAtStr  string       `orm:"-" json:"source_at" form:"source_at"`
	Timeslots    []*Timeslots `orm:"reverse(many)" json:"timeslots" form:"-"`
	TimeSlotJson string       `orm:"-" json:"-" form:"timeslots"`            
	Publish      int8         `orm:"column(publish);default(0)" json:"publish" form:"publish"`  //发布状态:0未发布;1发布
}

//可预约时间段,专属每一个peroid，可以单独更改，不影响其他peroid
type Timeslots struct {
	TimeslotsId    int64        `orm:"column(timeslots_id);pk;auto" json:"timeslots_id" form:"timeslots_id"`
	PartnerId     int64        `orm:"column(partner_id)" json:"partner_id" form:"partner_id"`
	TimeslotNo    int          `orm:"column(timeslot_no)" json:"timeslot_no" form:"timeslot_no"`           //时段序号
	TimeslotLabel string       `orm:"column(timeslot_label)" json:"timeslot_label" form:"timeslot_label"`  //时段标签
	Periods       *Periods     `orm:"column(periods_id);rel(fk);on_delete(cascade)" json:"-"`               //级联删除
    PeriodsId      int64        `orm:"-" json:"periods_id" form:"periods_id"`
	Start         string       `orm:"column(start);null" json:"start" form:"start"` //开始时间,非全日期时间,比如: 11:00
	End           string       `orm:"column(end);null" json:"end" form:"end"`       //结束时间,非全日期时间,比如: 12:00
	CurCount      int          `orm:"column(cur_count)" json:"cur_count" form:"cur_count"`  //当前预约量(每个peroid都可能不同)
	MaxCount      int          `orm:"column(max_count)" json:"max_count" form:"max_count"`  //最大可预约量
	Publish       int8         `orm:"column(publish);default(0)" json:"publish" form:"publish"`  //发布状态:0未发布;1发布
}

func (u *Periods) TableUnique() [][]string {
	return [][]string{
		[]string{"ResItem", "SourceAt"},
	}
}

func init() {
	orm.RegisterModel(new(Periods),new(Timeslots))
}

func AddPeriods(m *Periods) (id int64, err error) {
	o := models.GetDefaultDB()
	id, err = o.Insert(m)
	return
}

func AddMultiPeriods(list []*Periods) (err error) {
	size := len(list)
	o := models.GetDefaultDB()
	if size > 1 {
	    _, err = o.InsertMulti(size, list) 
	}else{
	   _, err = o.Insert(list[0])
	}
	return
}

func GetPeriodsById(id int64) (v *Periods, err error) {
	o := models.GetDefaultDB()
	v = &Periods{PeriodsId: id}
	if err = o.Read(v); err == nil {
		v.ResItemId = v.ResItem.ResItemId
		v.SourceAtStr = v.SourceAt.Format(consts.DATE_FORMAT)
		v.ResItem = nil
		return v, nil
	}
	return nil, err
}

func GetAllPeriods(query map[string]string,fields []string,order_by map[string]string,offset int,limit int)([]*Periods, int64,error) {
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(Periods))
	if start, ok := query["start_source_at"]; ok {
		if startTime, err := time.Parse(consts.DATE_FORMAT, start); err == nil {
		    qs = qs.Filter("source_at__gte", startTime)
		}
		delete(query, "start_source_at")
	}
	if end, ok := query["end_source_at"]; ok {
		if endTime, err := time.Parse(consts.DATE_FORMAT, end); err == nil {
	        qs = qs.Filter("source_at__lte", endTime)
	    }
		delete(query, "end_source_at")
	}
	for k, v := range query {
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	cnt, err := qs.Count()
	var sortFields []string
	for k, v := range order_by {
		orderby := ""
		if v == "desc" {
			orderby = "-" + k
		} else if v == "asc" {
			orderby = k
		} else {
			return nil, 0, errors.New("Error: Invalid order. Must be either [asc|desc]")
		}
		sortFields = append(sortFields, orderby)
	}
	var lists []*Periods
	qs = qs.OrderBy(sortFields...)
	if _, err := qs.Limit(limit, offset).All(&lists, fields...); err == nil {
		for _, period := range lists {
		    o.LoadRelated(period, "Timeslots")
			for _, timeslot := range period.Timeslots {   
				timeslot.Periods = nil
		    }
			period.ResItemId = period.ResItem.ResItemId
            period.SourceAtStr = period.SourceAt.Format(consts.DATE_FORMAT)
		    period.ResItem = nil
		}
		return lists, cnt, nil
	}
	return nil, 0, err
}

func GetPeriodsIdByDate(sourceAt time.Time, resItemId int64, publish int)(periodId int64, err error) {
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(Periods))
	qs = qs.Filter("source_at__gte", sourceAt)
	qs = qs.Filter("source_at__lte", sourceAt)
	qs = qs.Filter("res_item_id", resItemId)
	if publish > 0 {
	   qs = qs.Filter("publish", publish)
	}else{
	   qs = qs.Filter("publish", 0)
	}
	period := new(Periods)
	if err = qs.One(period); err == nil {
		return period.PeriodsId, nil
	}
	return -1, err
}

func GetPeriodsIdByResItemId(resItemId int64, publish int)(periodIds []int64, err error) {
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(Periods))
	qs = qs.Filter("res_item_id", resItemId)
	qs = qs.Filter("publish", publish)
	var lists []*Periods
	if _, err = qs.All(&lists); err == nil {
		for _, period := range lists {
			periodIds = append(periodIds, period.PeriodsId)
	    }
		return
	}
	return
}

func UpdatePeriodsById(m *Periods, k ...string) (err error) {
	o := models.GetDefaultDB()
	v := Periods{PeriodsId: m.PeriodsId}
	if err = o.Read(&v); err != nil {
		return err
	}else{
	    if _, err = o.Update(m, k...); err != nil {
		   return err
		}
	}
	return nil
}

func DeletePeriodsById(id int64) (err error) {
	o := models.GetDefaultDB()
	v := Periods{PeriodsId: id}
	if err = o.Read(&v); err == nil {
		if _, err = o.Delete(&v); err == nil {
			return nil
		}
	}
	return
}

func DeletePeriodsByMultiCond(partnerId,resItemId,periodsId int64,start,end string) (err error) {
    o := models.GetDefaultDB()
	qs := o.QueryTable(new(Periods))
	qs = qs.Filter("partner_id", partnerId)
	if resItemId > 0 {
	   qs = qs.Filter("res_item_id", resItemId)
	}
	if periodsId > 0 {
	   qs = qs.Filter("periods_id", periodsId)
	}
	if len(start) == 10 && len(end) == 10 {
		if startAt, err := time.Parse(consts.DATE_FORMAT,start); err == nil {
			if endAt, err := time.Parse(consts.DATE_FORMAT,end); err == nil {
			    qs = qs.Filter("source_at__gte", startAt)
	            qs = qs.Filter("source_at__lte", endAt)
	        }
		}  
	}
	_, err = qs.Delete()
	return
}

func DeletePeriodsByPublish(partnerId,resItemId int64) (err error) {
    o := models.GetDefaultDB()
	qs := o.QueryTable(new(Periods))
	qs = qs.Filter("partner_id", partnerId)
	if resItemId > 0 {
	   qs = qs.Filter("res_item_id", resItemId)
	}
	qs = qs.Filter("publish", 0)
	_, err = qs.Delete()
	return
}

/****************************************/
func AddTimeslots(m *Timeslots) (id int64, err error) {
	o := models.GetDefaultDB()
	id, err = o.Insert(m)
	return
}

func AddMultiTimeslots(list []*Timeslots) (err error) {
	size := len(list)
	o := models.GetDefaultDB()
	if size > 1 {
	    _, err = o.InsertMulti(size, list) 
	} else if size == 1 {
	   _, err = o.Insert(list[0])
	} else {
	
	}
	return
}

func GetTimeslotsById(id int64) (v *Timeslots, err error) {
	o := models.GetDefaultDB()
	v = &Timeslots{TimeslotsId: id}
	if err = o.Read(v); err == nil {
		v.PeriodsId = v.Periods.PeriodsId
		v.Periods = nil
		return v, nil
	}
	return nil, err
}
//查询所有餐桌
func GetAllTimeslots(query map[string]string,fields []string,order_by map[string]string,offset int,limit int)([]*Timeslots, int64,error) {
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(Timeslots))
	for k, v := range query {
		k = strings.Replace(k, ".", "__", -1)
		qs = qs.Filter(k, v)
	}
	cnt, err := qs.Count()
	var sortFields []string
	for k, v := range order_by {
		orderby := ""
		if v == "desc" {
			orderby = "-" + k
		} else if v == "asc" {
			orderby = k
		} else {
			return nil, 0, errors.New("Error: Invalid order. Must be either [asc|desc]")
		}
		sortFields = append(sortFields, orderby)
	}
	var lists []*Timeslots
	qs = qs.OrderBy(sortFields...)
	if _, err := qs.Limit(limit, offset).All(&lists, fields...); err == nil {
		for _, timeslot := range lists {
			timeslot.PeriodsId = timeslot.Periods.PeriodsId
			timeslot.Periods = nil
	    }
		return lists, cnt, nil
	}
	return nil, 0, err
}

func GetTimeslotIdsByPeriods(partnerId, periodsId int64)(timeslotIds []int64, err error) {
	o := models.GetDefaultDB()
	qs := o.QueryTable(new(Timeslots))
	qs = qs.Filter("partner_id", partnerId)
    qs = qs.Filter("periods_id", periodsId)
	var lists []*Timeslots
	if _, err = qs.All(&lists); err == nil {
		for _, timeslot := range lists {
			timeslotIds = append(timeslotIds, timeslot.TimeslotsId)
	    }
		return
	}
	return
}

func UpdateTimeslotsById(m *Timeslots, k ...string) (err error) {
	o := models.GetDefaultDB()
	v := Timeslots{TimeslotsId: m.TimeslotsId}
	if err = o.Read(&v); err != nil {
		return err
	}else{
	    if _, err = o.Update(m, k...); err != nil {
		   return err
		}
	}
	return nil
}
func DeleteTimeslots(id int64) (err error) {
	o := models.GetDefaultDB()
	v := Timeslots{TimeslotsId: id}
	if err = o.Read(&v); err == nil {
		if _, err = o.Delete(&v); err == nil {
			return nil
		}
	}
	return
}

func DeleteTimeslotsByMultiCond(partnerId, periodsId, timeslotsId int64) (err error) {
    o := models.GetDefaultDB()
	qs := o.QueryTable(new(Timeslots))
	qs = qs.Filter("partner_id", partnerId)
	if periodsId > 0 {
	   qs = qs.Filter("periods_id", periodsId)
	}
	if timeslotsId > 0 {
	   qs = qs.Filter("timeslots_id", timeslotsId)
	}
	_, err = qs.Delete()
	return
}
